package com.tutk.ipcam;

import android.annotation.SuppressLint;
import android.app.Application;
import android.app.Fragment;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.LinearLayout;

import com.tutk.IOTC.AVIOCTRLDEFs;
import com.tutk.IOTC.Camera;
import com.tutk.IOTC.CameraListener;
import com.tutk.IOTC.IMonitor;
import com.tutk.IOTC.IOTCAPIs;
import com.tutk.IOTC.IRegisterIOTCListener;
import com.tutk.IOTC.MediaCodecListener;
import com.tutk.IOTC.MediaCodecMonitor;
import com.tutk.IOTC.Packet;
import com.tutk.IOTC.St_SInfo;
import com.tutk.P2PCam264.MyCamera;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;

import cn.innosmart.aq.R;

public class CameraDevice implements IRegisterIOTCListener, IpCamera {

    public static final String TAG = "CameraDevice";
    public static final String NAME = "name";
    public static final String UID = "uid";
    public static final String ACCOUNT = "account";
    public static final String PASSWORD = "password";
    public static final int STS_CHANGE_CHANNEL_STREAMINFO = 99;
    public static final int RECEIVE_FRAME_DATA = 100;
    private final Object recordingLock = new Object();
    private final Application mApp;
    private final int THUMBNAIL_LIMIT_HEIGHT = 720;
    private final int THUMBNAIL_LIMIT_WIDTH = 1280;
    private final int maxReconnect = 5;
    public String name;
    public String uid;
    public String account;
    public String password;
    public boolean received = false;
    public Bitmap snapshot;
    // --- IRegisterIOTCListener ---
    private Context mCtx;
    private MyCamera camera;
    private int selectedChannel = 0;
    private int mVideoWidth;
    private int mVideoHeight;
    private IMonitor mMonitor;
    private IMonitor hardMonitor;
    private IMonitor softMonitor;
    private Handler handler;
    private OnStreamInfoUpdate mOnStreamInfoUpdate;
    private boolean isRecording;
    private boolean isListening;
    private boolean isSpeaking;
    private AsyncCallback<Integer> mSetPasswordCallback;
    private AsyncCallback<Integer> mGetVideoQualityCallback;
    private AsyncCallback<Integer> mGetVideoModeCallback;
    private AsyncCallback<Integer> mSetWifiCallback;
    private AsyncCallback<ArrayList<AVIOCTRLDEFs.SWifiAp>> mGetWifiListCallback;
    private MonitorFragment monitorFragment;
    private ArrayList<AVIOCTRLDEFs.SWifiAp> sWifiAps = new ArrayList<>();
    private int reconnectCount = 0;
    private boolean mSoftCodecCurrent = false;
    private boolean unavailable = false;

    public CameraDevice(Context ctx, String name, final String uid, String account, String password) {
        mCtx = ctx;
        mApp = (Application) mCtx.getApplicationContext();
        //mApp.registerActivityLifecycleCallbacks(this);
        this.name = name;
        this.uid = uid;
        this.account = account;
        this.password = password;
        this.camera = new MyCamera(name, uid, account, password);
        handler = new MyHandler(this);
        //monitor = new MediaCodecMonitor(mCtx, null);
        init();
    }

    public static File getOutputMediaFile(Context ctx, String uuid) {
        // To be safe, you should check that the SDCard is mounted
        // using Environment.getExternalStorageState() before doing this.
        File mediaStorageDir = ctx.getFilesDir();

        // This location works best if you want the created images to be shared
        // between applications and persist after your app has been uninstalled.

        // Create the storage directory if it does not exist
        if (!mediaStorageDir.exists()) {
            if (!mediaStorageDir.mkdirs()) {
                return null;
            }
        }
        // Create a media file name
        //String timeStamp = new SimpleDateFormat("ddMMyyyy_HHmm").format(new Date());
        String mImageName = "camera_" + uuid + ".jpg";
        return new File(mediaStorageDir.getPath() + File.separator + mImageName);
    }

    public void reInit(String name, final String uid, String password) {
        this.name = name;
        this.uid = uid;
        this.password = password;
        this.camera.reset(name, uid, account, password);
    }

    public void init() {
        camera.registerIOTCListener(this);
        camera.SetCameraListener(new CameraListener() {
            @Override
            public void OnSnapshotComplete() {
                Log.d("kukuri", "fuck OnSnapshotComplete() called.");
            }
        });
        //if (!camera.isSessionConnected()) {
        camera.connect(uid);
        camera.start(MyCamera.DEFAULT_AV_CHANNEL, account, password);
//        {
//            @Override
//            public void Unavailable() {camera.start(MyCamera.DEFAULT_AV_CHANNEL, account, password);
//        camera.sendIOCtrl(Camera.DEFAULT_AV_CHANNEL,
//                AVIOCTRLDEFs.IOTYPE_USER_IPCAM_GETSUPPORTSTREAM_REQ,
//                AVIOCTRLDEFs.SMsgAVIoctrlGetSupportStreamReq.parseContent());
//        camera.sendIOCtrl(Camera.DEFAULT_AV_CHANNEL,
//                AVIOCTRLDEFs.IOTYPE_USER_IPCAM_DEVINFO_REQ,
//                AVIOCTRLDEFs.SMsgAVIoctrlDeviceInfoReq.parseContent());
//        camera.sendIOCtrl(Camera.DEFAULT_AV_CHANNEL,
//                AVIOCTRLDEFs.IOTYPE_USER_IPCAM_GETAUDIOOUTFORMAT_REQ,
//                AVIOCTRLDEFs.SMsgAVIoctrlGetAudioOutFormatReq
//                        .parseContent());
//        camera.sendIOCtrl(Camera.DEFAULT_AV_CHANNEL,
//                AVIOCTRLDEFs.IOTYPE_USER_IPCAM_GET_TIMEZONE_REQ,
//                AVIOCTRLDEFs.SMsgAVIoctrlTimeZone.parseContent());
        //}
//
//        mMonitor.setMediaCodecListener(new MediaCodecListener()
//                Log.d("kukuri", "fuck Unavailable() called.");
//            }
//
//            @Override
//            public void zoomSurface(float v) {
//            }
//        });
    }

    @Override
    public Fragment getView() {
        return new MonitorFragment(this);
    }

    @Override
    public Bitmap getSnapshot() {
        Bitmap bitmapFromCamera = getSnapshotFromCamera();
        if (bitmapFromCamera != null) {
            return bitmapFromCamera;
        }
        BitmapFactory.Options options = new BitmapFactory.Options();
        //options.inPreferredConfig = Bitmap.Config.ARGB_8888;
        options.inJustDecodeBounds = false;
        options.inPreferredConfig = Bitmap.Config.RGB_565;
        options.inDither = true;
        File outputMediaFile = getOutputMediaFile(mCtx, uid);
        if (outputMediaFile == null) {
            return null;
        }
        String path = outputMediaFile.getPath();
        return BitmapFactory.decodeFile(path, options);
    }

    @Override
    public void record(int secs, String path, RecordingCallback lis) {
        startRecoding(secs, path, lis);
    }

    @Override
    public void disconnect() {
        stopP2PCameraInThread();
    }

    @Override
    public void listen() {
        if (isSpeaking) {
            mute();
        }
        camera.startListening(selectedChannel, true);
        isListening = true;
    }

    @Override
    public void mute() {
        camera.stopListening(selectedChannel);
        camera.stopSpeaking(selectedChannel);
        isListening = isSpeaking = false;
    }

    @Override
    public void speak() {
        if (isListening) {
            mute();
        }
        camera.startSpeaking(selectedChannel);
        isSpeaking = true;
    }

    @Override
    public void setOnStreamInfoUpdate(OnStreamInfoUpdate lis) {
        mOnStreamInfoUpdate = lis;
    }

    @Override
    public void reconnect() {
        if (reconnectCount <= maxReconnect) {
            reconnectCount++;
            disconnect();
            init();
        }

    }

    @Override
    public void setPassword(String oldPassword, String newPassword, AsyncCallback cb) {
        camera.setPassword(newPassword);
        this.password = newPassword;
        camera.sendIOCtrl(Camera.DEFAULT_AV_CHANNEL, AVIOCTRLDEFs.IOTYPE_USER_IPCAM_SETPASSWORD_REQ, AVIOCTRLDEFs.SMsgAVIoctrlSetPasswdReq.parseContent(oldPassword, newPassword));
        mSetPasswordCallback = cb;
    }

    @Override
    public void getVideoQuality(AsyncCallback cb) {
        camera.sendIOCtrl(Camera.DEFAULT_AV_CHANNEL, AVIOCTRLDEFs.IOTYPE_USER_IPCAM_GETSTREAMCTRL_REQ, AVIOCTRLDEFs.SMsgAVIoctrlGetStreamCtrlReq.parseContent(selectedChannel));
        mGetVideoQualityCallback = cb;
    }

    @Override
    public void getWifiList(AsyncCallback cb) {
        camera.sendIOCtrl(Camera.DEFAULT_AV_CHANNEL, AVIOCTRLDEFs.IOTYPE_USER_IPCAM_LISTWIFIAP_REQ, AVIOCTRLDEFs.SMsgAVIoctrlGetWifiReq.parseContent());
        mGetWifiListCallback = cb;
    }

    public void setVideoQuality(int videoQuality) {
        //mVideoQuality = videoQuality;

        if (videoQuality != -1) {
            camera.sendIOCtrl(Camera.DEFAULT_AV_CHANNEL, AVIOCTRLDEFs.IOTYPE_USER_IPCAM_SETSTREAMCTRL_REQ, AVIOCTRLDEFs.SMsgAVIoctrlSetStreamCtrlReq.parseContent(selectedChannel, (byte) (videoQuality + 1)));
//            try {
//                Thread.sleep(500);
//                reconnect();
//            } catch (InterruptedException e) {
//                e.printStackTrace();
//            }
        }
    }

    @Override
    public void getVideoMode(AsyncCallback<Integer> cb) {
        camera.sendIOCtrl(Camera.DEFAULT_AV_CHANNEL, AVIOCTRLDEFs.IOTYPE_USER_IPCAM_GET_VIDEOMODE_REQ, AVIOCTRLDEFs.SMsgAVIoctrlGetVideoModeReq.parseContent(selectedChannel));
        mGetVideoModeCallback = cb;
    }

    @Override
    public void setWifi(AVIOCTRLDEFs.SWifiAp sWifiAp, String password, AsyncCallback<Integer> cb) {
        camera.sendIOCtrl(Camera.DEFAULT_AV_CHANNEL, AVIOCTRLDEFs.IOTYPE_USER_IPCAM_SETWIFI_REQ, AVIOCTRLDEFs.SMsgAVIoctrlSetWifiReq.parseContent(sWifiAp.ssid, password.getBytes(), sWifiAp.mode, sWifiAp.enctype));
        mSetWifiCallback = cb;
    }

    @Override
    public void setVideoMode(int videoMode) {

        if (videoMode != -1) {
            camera.sendIOCtrl(Camera.DEFAULT_AV_CHANNEL, AVIOCTRLDEFs.IOTYPE_USER_IPCAM_SET_VIDEOMODE_REQ, AVIOCTRLDEFs.SMsgAVIoctrlSetVideoModeReq.parseContent(selectedChannel, (byte) videoMode));
//            try {
//                Thread.sleep(500);
//                reconnect();
//            } catch (InterruptedException e) {
//                e.printStackTrace();
//            }
        }
    }

    public void setMonitor(IMonitor monitor) {
        mMonitor = monitor;
    }

    @Override
    public void receiveFrameData(final Camera camera, int avChannel, Bitmap bmp) {

        if (this.camera == camera && avChannel == selectedChannel) {

            if (bmp != null && (bmp.getWidth() != mVideoWidth || bmp.getHeight() != mVideoHeight)) {
                mVideoWidth = bmp.getWidth();
                mVideoHeight = bmp.getHeight();
//                reScaleMonitor();
            }
        }
    }

    @Override
    public void receiveFrameDataForMediaCodec(Camera camera, int i, byte[] bytes, int i1, int i2, byte[] bytes1, boolean b, int i3) {

    }

    @Override
    public void receiveFrameInfo(final Camera camera, int avChannel,
                                 long bitRate, int frameRate, int onlineNm, int frameCount,
                                 int incompleteFrameCount) {
        if (this.camera == camera && avChannel == selectedChannel) {

            Bundle bundle = new Bundle();
            bundle.putInt("avChannel", avChannel);
            Message msg = handler.obtainMessage();
            msg.what = STS_CHANGE_CHANNEL_STREAMINFO;
            msg.setData(bundle);
            msg.sendToTarget();
        }
    }

    @Override
    public void receiveSessionInfo(final Camera camera, int resultCode) {
        if (this.camera == camera) {
            Bundle bundle = new Bundle();
            Message msg = handler.obtainMessage();
            msg.what = resultCode;
            msg.setData(bundle);
            msg.sendToTarget();
        }
    }

    @Override
    public void receiveChannelInfo(final Camera camera, int avChannel,
                                   int resultCode) {

        if (this.camera == camera && avChannel == selectedChannel) {
            Bundle bundle = new Bundle();
            bundle.putInt("avChannel", avChannel);

            Message msg = handler.obtainMessage();
            msg.what = resultCode;
            msg.setData(bundle);
            msg.sendToTarget();
        }
    }

    @Override
    public void receiveIOCtrlData(final Camera camera, int avChannel,
                                  int avIOCtrlMsgType, byte[] data) {

        if (this.camera == camera) {

            Bundle bundle = new Bundle();
            bundle.putInt("avChannel", avChannel);
            bundle.putByteArray("data", data);
            Message msg = handler.obtainMessage();
            msg.what = avIOCtrlMsgType;
            msg.setData(bundle);
            msg.sendToTarget();
        }

    }

    private boolean startRecoding(int secs, String path, final RecordingCallback lis) {
        secs += 2; // FIXME: some time error due to first iframe
        synchronized (recordingLock) {
            if (isRecording) return false;
            /*
            if (!mIsListening && !mIsSpeaking) {
                cameraDevice.getCamera().startListening(0);
                mIsListening = true;
                startListeningByRecording = true;
            }
            */

            boolean result = camera.startRecording(path);

            if (result) {
                isRecording = true;
                lis.onRecordStart();
                handler.postDelayed(new Runnable() {
                    // update videoRecordingButton Src
                    boolean state;

                    @Override
                    public void run() {
                        if (!isRecording)
                            return;
                        /*
                        if(state)
                            videoRecordingButton.setImageResource(R.drawable.ic_video_recording_onair1) ;
                        else
                            videoRecordingButton.setImageResource(R.drawable.ic_video_recording_onair2) ;
                            */
                        state = !state;
                        handler.postDelayed(this, 500);
                    }
                }, 0);
                if (secs > 0) handler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        stopRecording(lis);
                    }
                }, secs * 1000);
            }
            return result;
        }
    }

    private boolean stopRecording(RecordingCallback lis) {
        synchronized (recordingLock) {
            if (!isRecording) return false;
            /*
            if (mIsListening && startListeningByRecording) {
                cameraDevice.getCamera().stopListening(0);
                mIsListening = false;
                startListeningByRecording = false;
            }
            */
            boolean result = camera.stopRecording();
            if (result) {
                isRecording = false;
                lis.onRecordFinished();
            }
            return result;
        }
    }

    private void stopP2PCameraInThread() {
        if (camera != null) {
            if (mMonitor != null)
                mMonitor.deattachCamera();
            camera.unregisterIOTCListener(this);
            // camera.stopSpeaking(selectedChannel);
            // camera.stopListening(selectedChannel);
            camera.stopShow(selectedChannel);
            if (isListening) {
                camera.stopListening(selectedChannel);
            }
            if (isSpeaking) {
                camera.stopSpeaking(selectedChannel);
            }

            camera.disconnect();
            //Camera.uninit();
        }
    }

    private void startShow() {
        camera.startShow(selectedChannel, true, mSoftCodecCurrent);
        mMonitor.setMaxZoom(3.0f);
        mMonitor.enableDither(camera.mEnableDither);
        mMonitor.attachCamera(camera, selectedChannel);
        if (isSpeaking) {
            speak();
        }
        if (isListening) {
            listen();
        }
    }

    private void start() {
//        camera.registerIOTCListener(this);
//        camera.SetCameraListener(new CameraListener() {
//            @Override
//            public void OnSnapshotComplete() {
//                Log.d("kukuri", "fuck OnSnapshotComplete() called.");
//            }
//        });
        //if (!camera.isSessionConnected()) {
//        camera.connect(uid);
        camera.start(MyCamera.DEFAULT_AV_CHANNEL, account, password);
        camera.sendIOCtrl(Camera.DEFAULT_AV_CHANNEL,
                AVIOCTRLDEFs.IOTYPE_USER_IPCAM_GETSUPPORTSTREAM_REQ,
                AVIOCTRLDEFs.SMsgAVIoctrlGetSupportStreamReq.parseContent());
        camera.sendIOCtrl(Camera.DEFAULT_AV_CHANNEL,
                AVIOCTRLDEFs.IOTYPE_USER_IPCAM_DEVINFO_REQ,
                AVIOCTRLDEFs.SMsgAVIoctrlDeviceInfoReq.parseContent());
        camera.sendIOCtrl(Camera.DEFAULT_AV_CHANNEL,
                AVIOCTRLDEFs.IOTYPE_USER_IPCAM_GETAUDIOOUTFORMAT_REQ,
                AVIOCTRLDEFs.SMsgAVIoctrlGetAudioOutFormatReq
                        .parseContent());
        camera.sendIOCtrl(Camera.DEFAULT_AV_CHANNEL,
                AVIOCTRLDEFs.IOTYPE_USER_IPCAM_GET_TIMEZONE_REQ,
                AVIOCTRLDEFs.SMsgAVIoctrlTimeZone.parseContent());
        //}

//        mMonitor.setMediaCodecListener(new MediaCodecListener() {
//            @Override
//            public void Unavailable() {
//
//                Log.d("kukuri", "fuck Unavailable() called.");
//            }
//
//            @Override
//            public void zoomSurface(float v) {
//            }
//        });
        startShow();
        /*
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                Log.d("kukuri", "postDelayed() called");

                mMonitor.deattachCamera();
                if (camera != null) {
                    camera.stopShow(selectedChannel);
                    mIsUsingSoftDecode = true;
                    startShow();
                }
            }
        }, 1000);
        */
    }

    private Bitmap getSnapshotFromCamera() {
        if (this.camera == null)
            return this.snapshot;

        Bitmap bitmap = this.camera.Snapshot(this.selectedChannel);
        if (bitmap != null)
            this.snapshot = Bitmap.createBitmap(bitmap);
        else
            this.received = false;

        return this.snapshot;
    }

    private MyCamera getCamera() {
        return this.camera;
    }

    private int getSelectedChannel() {
        return this.selectedChannel;
    }

    private Bitmap compressImage(Bitmap image) {
        try {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            image.compress(Bitmap.CompressFormat.JPEG, 5, baos);
            ByteArrayInputStream isBm = new ByteArrayInputStream(
                    baos.toByteArray());
            return BitmapFactory.decodeStream(isBm, null, null);

        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

    private void storeImage(Bitmap image, String uuid) {
        if (image == null) return;
        File pictureFile = getOutputMediaFile(mCtx, uuid);
        if (pictureFile == null) {
            Log.d(TAG,
                    "Error creating media file, check storage permissions: ");// e.getMessage());
            return;
        }
        try {
            FileOutputStream fos = new FileOutputStream(pictureFile);
            image.compress(Bitmap.CompressFormat.PNG, 90, fos);
            fos.close();
        } catch (FileNotFoundException e) {
            Log.d(TAG, "File not found: " + e.getMessage());
        } catch (IOException e) {
            Log.d(TAG, "Error accessing file: " + e.getMessage());
        }
    }

    public void stopShow() {
        try {
            Bitmap bmp = getSnapshot();
            if (bmp != null) {
                bmp = compressImage(bmp);
                if (bmp.getWidth() * bmp.getHeight() > THUMBNAIL_LIMIT_WIDTH
                        * THUMBNAIL_LIMIT_HEIGHT) {
                    bmp = Bitmap.createScaledBitmap(bmp, THUMBNAIL_LIMIT_WIDTH,
                            THUMBNAIL_LIMIT_HEIGHT, false);
                }
                storeImage(bmp, uid);
                //snapshot = DatabaseManager.getByteArrayFromBitmap(bmp);
            }
        } catch (Exception e) {
            Log.d("kukuri", "Snapshot not saved.");
            e.printStackTrace();
        }
//            mCameraDevice.stopP2PCameraInThread();
//            disconnect();
        if (camera != null) {
//                camera.stop(selectedChannel);
            System.out.println("stopShow");

            camera.stopShow(MyCamera.DEFAULT_AV_CHANNEL);
            if(mMonitor == null) {
                return;
            }
            mMonitor.deattachCamera();
//                camera.unregisterIOTCListener(this);
            // camera.stopSpeaking(selectedChannel);
            // camera.stopListening(selectedChannel);
            if (isListening) {
                camera.stopListening(selectedChannel);
            }
            if (isSpeaking) {
                camera.stopSpeaking(selectedChannel);
            }
//                camera.disconnect();
            //Camera.uninit();
        }
    }

    public ArrayList<AVIOCTRLDEFs.SWifiAp> getsWifiAps() {
        return sWifiAps;
    }

    public void setsWifiAps(ArrayList<AVIOCTRLDEFs.SWifiAp> sWifiAps) {
        this.sWifiAps = sWifiAps;
    }

    private static class MyHandler extends Handler {

        private final WeakReference<CameraDevice> mWeakCameraDevice;

        public MyHandler(CameraDevice cameraDevice) {
            mWeakCameraDevice = new WeakReference<>(cameraDevice);
        }

        @Override
        public void handleMessage(Message msg) {

            CameraDevice cameraDevice = mWeakCameraDevice.get();
            if (cameraDevice == null) {
                return;
            }

            Bundle bundle = msg.getData();
            //int avChannel = bundle.getInt("avChannel");
            byte[] data = bundle.getByteArray("data");

            St_SInfo stSInfo = new St_SInfo();
            IOTCAPIs.IOTC_Session_Check(cameraDevice.camera.getMSID(), stSInfo);

            switch (msg.what) {
                case STS_CHANGE_CHANNEL_STREAMINFO:
                    Log.d("kukuri", "STS_CHANGE_CHANNEL_STREAMINFO");
                    if (cameraDevice.mOnStreamInfoUpdate != null) {
                        cameraDevice.mOnStreamInfoUpdate.onFrameRateUpdate(String.valueOf(MediaCodecMonitor.keepFPS));
                        cameraDevice.mOnStreamInfoUpdate.onFrameResolutionUpdate(String.valueOf(Camera.view_Width)
                                + "x" + String.valueOf(Camera.view_Height));
                    }
                    break;

                //case STS_SNAPSHOT_SCANED:
                case AVIOCTRLDEFs.IOTYPE_USER_IPCAM_SETPASSWORD_RESP:
                    System.out.println("ModifyPassword RESP");
                    break;
                case AVIOCTRLDEFs.IOTYPE_USER_IPCAM_LISTWIFIAP_RESP:
                    cameraDevice.sWifiAps.clear();
                    System.out.println("IOTYPE_USER_IPCAM_GETWIFI_RESP RESP");
                    System.out.println("msg.w=" + msg.toString());
                    System.out.println("msg.w=" + msg.toString());
                    byte[] numbers = new byte[4];
                    byte[] datas;
                    System.arraycopy(data, 0, numbers, 0, 4);
                    int index = Packet.byteArrayToInt_Little(numbers);
                    Set set = new HashSet();
                    for (int i = 0; i < index; i++) {
                        datas = new byte[36];
                        System.arraycopy(data, 4 + 36 * i, datas, 0, 36);
                        AVIOCTRLDEFs.SWifiAp sWifiAp = new AVIOCTRLDEFs.SWifiAp(datas);
                        if (set.add(sWifiAp.name))
                            cameraDevice.sWifiAps.add(sWifiAp);
                    }
                    if (cameraDevice.mGetWifiListCallback != null) {
                        cameraDevice.mGetWifiListCallback.onSuccess(cameraDevice.sWifiAps);
                    }
                    break;
                case AVIOCTRLDEFs.IOTYPE_USER_IPCAM_GETWIFI_RESP:
                    System.out.println("IOTYPE_USER_IPCAM_GETWIFI_RESP RESP");
                    break;
                case AVIOCTRLDEFs.IOTYPE_USER_IPCAM_SETWIFI_RESP:
                    System.out.println("IOTYPE_USER_IPCAM_SETWIFI_RESP RESP");
                    int result = data[0];
                    if (cameraDevice.mSetWifiCallback != null) {
                        cameraDevice.mSetWifiCallback.onSuccess(result);
                    }
                    break;
                //break;
                case AVIOCTRLDEFs.IOTYPE_USER_IPCAM_GETSTREAMCTRL_RESP:
                    if (data == null) break;

                    int videoQuality = data[4];

                    if (videoQuality > 0 && videoQuality < 6) {
                        //mVideoQuality = videoQuality - 1;
                        cameraDevice.mGetVideoQualityCallback.onSuccess(videoQuality - 1);
                    }
                    break;

                case AVIOCTRLDEFs.IOTYPE_USER_IPCAM_GET_VIDEOMODE_RESP:
                    int videoMode = data[4];
                    if (videoMode >= 0 && videoMode <= 3) {
                        cameraDevice.mGetVideoModeCallback.onSuccess(videoMode);
                    }
                    break;

                case Camera.CONNECTION_STATE_CONNECTING:
                    Log.d("kukuri", "UID=" + cameraDevice.uid + "CONNECTION_STATE_CONNECTING");
                    if (cameraDevice.mOnStreamInfoUpdate != null) {
                        cameraDevice.mOnStreamInfoUpdate.onCameraStatus(cameraDevice.uid, Camera.CONNECTION_STATE_CONNECTING);
                    } else {
                        Log.d("DEBUG", "监听器为空！！！！");
                    }
                    break;

                case Camera.CONNECTION_STATE_CONNECTED:
                    Log.d("kukuri", "UID=" + cameraDevice.uid + "CONNECTION_STATE_CONNECTED");
                    if (cameraDevice.mOnStreamInfoUpdate != null) {
                        cameraDevice.reconnectCount = 0;
                        cameraDevice.mOnStreamInfoUpdate.onCameraStatus(cameraDevice.uid, Camera.CONNECTION_STATE_CONNECTED);
                    } else {
                        Log.d("DEBUG", "监听器为空！！！！");
                    }
                    break;

                case Camera.CONNECTION_STATE_DISCONNECTED:
                    Log.d("kukuri", "UID=" + cameraDevice.uid + "CONNECTION_STATE_DISCONNECTED");
                    if (cameraDevice.mOnStreamInfoUpdate != null) {
                        cameraDevice.mOnStreamInfoUpdate.onCameraStatus(cameraDevice.uid, Camera.CONNECTION_STATE_DISCONNECTED);
                    } else {
                        Log.d("DEBUG", "监听器为空！！！！");
                    }
                    break;

                case Camera.CONNECTION_STATE_UNKNOWN_DEVICE:
                    Log.d("kukuri", "UID=" + cameraDevice.uid + "CONNECTION_STATE_UNKNOWN_DEVICE");
                    if (cameraDevice.mOnStreamInfoUpdate != null) {
                        cameraDevice.mOnStreamInfoUpdate.onCameraStatus(cameraDevice.uid, Camera.CONNECTION_STATE_UNKNOWN_DEVICE);
                    } else {
                        Log.d("DEBUG", "监听器为空！！！！");
                    }
                    break;

                case Camera.CONNECTION_STATE_TIMEOUT:
                    Log.d("kukuri", "UID=" + cameraDevice.uid + "CONNECTION_STATE_TIMEOUT");
                    if (cameraDevice.mOnStreamInfoUpdate != null) {
                        cameraDevice.mOnStreamInfoUpdate.onCameraStatus(cameraDevice.uid, Camera.CONNECTION_STATE_TIMEOUT);
                    } else {
                        Log.d("DEBUG", "监听器为空！！！！");
                    }
                    break;

                case Camera.CONNECTION_STATE_CONNECT_FAILED:
                    Log.d("kukuri", "UID=" + cameraDevice.uid + "CONNECTION_STATE_CONNECT_FAILED");
                    if (cameraDevice.mOnStreamInfoUpdate != null) {
                        cameraDevice.mOnStreamInfoUpdate.onCameraStatus(cameraDevice.uid, Camera.CONNECTION_STATE_CONNECT_FAILED);
                    } else {
                        Log.d("DEBUG", "监听器为空！！！！");
                    }
                    break;

                case Camera.CONNECTION_STATE_WRONG_PASSWORD:
                    Log.d("kukuri", "UID=" + cameraDevice.uid + "CONNECTION_STATE_WRONG_PASSWORD");
                    if (cameraDevice.mOnStreamInfoUpdate != null) {
                        cameraDevice.mOnStreamInfoUpdate.onCameraStatus(cameraDevice.uid, Camera.CONNECTION_STATE_WRONG_PASSWORD);
                    } else {
                        Log.d("DEBUG", "监听器为空！！！！");
                    }
                    break;

                case AVIOCTRLDEFs.IOTYPE_USER_IPCAM_GETSUPPORTSTREAM_RESP:
                    break;

                default:
                    super.handleMessage(msg);
            }

        }
    }

    /**
     * It's a valid fragment, really.
     */
    @SuppressLint("ValidFragment")
    public class MonitorFragment extends Fragment implements MediaCodecListener {

        private final int THUMBNAIL_LIMIT_HEIGHT = 720;
        private final int THUMBNAIL_LIMIT_WIDTH = 1280;
        private CameraDevice mCameraDevice;
        private LinearLayout rlHard;
        private LinearLayout rlSoft;
        private View view;
        private FrameLayout root;
        private boolean runSoftwareDecode = false;

        private MonitorFragment(CameraDevice cameraDevice) {
            mCameraDevice = cameraDevice;
        }

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
            Log.d("kukuri", "onCreateView() called");
            view = inflater.inflate(R.layout.camera_view, container, false);
            hardMonitor = (IMonitor) view.findViewById(R.id.hard_monitor);
            softMonitor = (IMonitor) view.findViewById(R.id.soft_monitor);
            rlHard = (LinearLayout) view.findViewById(R.id.rl_hard);
            rlSoft = (LinearLayout) view.findViewById(R.id.rl_soft);
            root = (FrameLayout) view.findViewById(R.id.root);
            hardMonitor.setMediaCodecListener(this);
//            mCameraDevice.setMonitor(hardMonitor);
            setupPortraitView(mSoftCodecCurrent);
            return view;
        }

        @Override
        public void onResume() {
            Log.d("kukuri", "onResume() called");
            super.onResume();
            mCameraDevice.start();
        }

        @Override
        public void onPause() {
            Log.d("kukuri", "onPause() called");
            try {
                Bitmap bmp = mCameraDevice.getSnapshot();
                if (bmp != null) {
                    bmp = compressImage(bmp);
                    if (bmp.getWidth() * bmp.getHeight() > THUMBNAIL_LIMIT_WIDTH
                            * THUMBNAIL_LIMIT_HEIGHT) {
                        bmp = Bitmap.createScaledBitmap(bmp, THUMBNAIL_LIMIT_WIDTH,
                                THUMBNAIL_LIMIT_HEIGHT, false);
                    }
                    storeImage(bmp, mCameraDevice.uid);
                    //snapshot = DatabaseManager.getByteArrayFromBitmap(bmp);
                }
            } catch (Exception e) {
                Log.d("kukuri", "Snapshot not saved.");
                e.printStackTrace();
            }
//            mCameraDevice.stopP2PCameraInThread();
//            disconnect();
            if (camera != null) {
//                camera.stop(selectedChannel);
                System.out.println("stopShow");

                camera.stopShow(MyCamera.DEFAULT_AV_CHANNEL);
//                mMonitor.deattachCamera();
//                camera.unregisterIOTCListener(this);
                // camera.stopSpeaking(selectedChannel);
                // camera.stopListening(selectedChannel);
                if (isListening) {
                    camera.stopListening(selectedChannel);
                }
                if (isSpeaking) {
                    camera.stopSpeaking(selectedChannel);
                }
//                camera.disconnect();
                //Camera.uninit();
            }
            super.onPause();
        }

        @Override
        public void onDestroyView() {
            super.onDestroyView();
            Log.d("kukuri", "onDestroyView() called");
            if (camera != null) {
                camera.stopShow(MyCamera.DEFAULT_AV_CHANNEL);
                mMonitor.deattachCamera();
                if (isListening) {
                    camera.stopListening(selectedChannel);
                }
                if (isSpeaking) {
                    camera.stopSpeaking(selectedChannel);
                }
//                camera.disconnect();
                //Camera.uninit();
            }
        }

        @Override
        public void onDetach() {
            Log.d("kukuri", "onDetach() called.");
            super.onDetach();
        }

        public void disconnect() {
            mCameraDevice.disconnect();
        }

        private Bitmap compressImage(Bitmap image) {
            try {
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                image.compress(Bitmap.CompressFormat.JPEG, 5, baos);
                ByteArrayInputStream isBm = new ByteArrayInputStream(
                        baos.toByteArray());
                return BitmapFactory.decodeStream(isBm, null, null);

            } catch (Exception e) {
                e.printStackTrace();
            }

            return null;
        }

        private void storeImage(Bitmap image, String uuid) {
            if (image == null) return;
            File pictureFile = getOutputMediaFile(getActivity(), uuid);
            if (pictureFile == null) {
                Log.d(TAG,
                        "Error creating media file, check storage permissions: ");// e.getMessage());
                return;
            }
            try {
                FileOutputStream fos = new FileOutputStream(pictureFile);
                image.compress(Bitmap.CompressFormat.PNG, 90, fos);
                fos.close();
            } catch (FileNotFoundException e) {
                Log.d(TAG, "File not found: " + e.getMessage());
            } catch (IOException e) {
                Log.d(TAG, "Error accessing file: " + e.getMessage());
            }
        }

        @Override
        public void Unavailable() {
            if (unavailable)
                return;
            unavailable = true;
            mSoftCodecCurrent = true;
            if (softMonitor != null) {
                softMonitor.deattachCamera();
            }
            if (softMonitor != null) {
                softMonitor.deattachCamera();
            }
            getActivity().runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    if (camera != null) {
                        camera.stopShow(selectedChannel);
                        handler.postDelayed(new Runnable() {
                            @Override
                            public void run() {
                                camera.startShow(selectedChannel, true, true);
                                setupPortraitView(true);
                            }
                        }, 1000);
                    }
                }
            });
        }

        @Override
        public void monitorIsReady() {

        }

        @Override
        public void zoomSurface(float v) {

        }

        private void setupLandscapeView() {

        }

        private void setupPortraitView(final boolean runSoftwareDecode) {
            mSoftCodecCurrent = false;
            if (runSoftwareDecode)
                mSoftCodecCurrent = true;
            if (!runSoftwareDecode) {
                rlHard.setVisibility(View.VISIBLE);
                rlSoft.setVisibility(View.GONE);
                hardMonitor = (IMonitor) view.findViewById(R.id.hard_monitor);
                hardMonitor.setMaxZoom(3.0f);
                hardMonitor.enableDither(camera.mEnableDither);
                hardMonitor.attachCamera(camera, selectedChannel);
                hardMonitor.cleanFrameQueue();
                hardMonitor.setMediaCodecListener(this);
                mCameraDevice.setMonitor(hardMonitor);
            } else {
//                so = (IMonitor) findViewById(R.id.softMonitor);
                rlSoft.setVisibility(View.VISIBLE);
                rlHard.setVisibility(View.GONE);
                softMonitor = (IMonitor) view.findViewById(R.id.soft_monitor);
                softMonitor.setMaxZoom(3.0f);
                softMonitor.enableDither(camera.mEnableDither);
                softMonitor.attachCamera(camera, selectedChannel);
                mCameraDevice.setMonitor(softMonitor);
            }
            int width = root.getWidth();
            int height = root.getHeight();
            System.out.println("width=" + width + "====height=" + height);
            if (width != 0 && height != 0) {
                System.out.println("width=" + view.findViewById(R.id.soft_monitor).getWidth() + "====height=" + view.findViewById(R.id.soft_monitor).getHeight());
                reScaleMonitor();
            }
        }

        private void reScaleMonitor() {
            if (mVideoHeight == 0 || mVideoWidth == 0)
                return;
            final SurfaceView surfaceView;
            if (mSoftCodecCurrent) {
                surfaceView = (SurfaceView) softMonitor;
            } else {
                surfaceView = (SurfaceView) hardMonitor;
            }
            surfaceView.getLayoutParams().width = mVideoWidth;
            surfaceView.getLayoutParams().height = mVideoHeight;
            getActivity().runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    // TODO Auto-generated method stub
                    surfaceView.setLayoutParams(surfaceView.getLayoutParams());
                }
            });
        }
    }

}
